#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;
int minSteps = INF; // 初始化最小步数为无穷大
const int MAX_ROWS = 30, MAX_COLS = 30;
int n, m;
int board[MAX_ROWS], temp[MAX_ROWS];

// 方向数组：中心、上、右、下、左
const int dx[5] = {0, 0, 1, 0, -1}, dy[5] = {0, 1, 0, -1, 0};

// 翻转指定位置及其相邻位置的棋子
void flip(int x, int y) {
  for (int i = 0; i <= 4; i++) {
    int nx = x + dx[i], ny = y + dy[i];
    if (nx < 0 || nx >= n || ny < 0 || ny >= m)
      continue;
    temp[nx] ^= (1 << ny);
  }
}

// 检查当前翻转方案是否有效，并返回所需步数
int check(int firstRowMask) {
  int steps = 0;
  memcpy(temp, board, sizeof(board));

  // 处理第一行的翻转
  for (int j = 0; j < m; j++) {
    if ((firstRowMask >> j) & 1) {
      flip(0, j);
      steps++;
      if (steps >= minSteps)
        return INF;
    }
  }

  // 处理中间行的翻转
  for (int i = 1; i < n; i++) {
    int prevRowState = temp[i - 1];
    if (prevRowState == 0)
      continue;

    for (int j = 0; j < m; j++) {
      if ((prevRowState >> j) & 1) {
        flip(i, j);
        steps++;
        if (steps >= minSteps)
          return INF;
      }
    }
  }

  // 检查最后一行是否全部为白色
  if (temp[n - 1] != 0)
    return INF;
  return steps;
}

int main() {
  scanf("%d%d", &n, &m);

  // 读取并存储初始棋盘状态
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      int k;
      scanf("%d", &k);
      board[i] = (board[i] << 1) | k;
    }
  }

  // 枚举第一行的所有可能翻转方案
  for (int mask = 0; mask < (1 << m); mask++) {
    int steps = check(mask);
    if (steps < minSteps) {
      minSteps = steps;
    }
  }

  if (minSteps != INF)
    printf("%d\n", minSteps);
  else
    printf("Impossible\n");
  return 0;
}